package support.common;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.xmlpull.v1.XmlPullParser;

import android.content.res.AXmlResourceParser;
import android.util.TypedValue;

public class ApkInfo {
	public static void scanZipFile(String zipname) {
		try {
			ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname));
			ZipEntry entry;
			while ((entry = zin.getNextEntry()) != null) {
				System.out.println(entry.getName());
				zin.closeEntry();
			}
			zin.close();
		} catch (IOException e) {
		}
	}

	public static InputStream loadZipFile(String zipname, String name) {
		try {
			ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname));
			ZipEntry entry;
			while ((entry = zin.getNextEntry()) != null) {
				if (entry.getName().equals(name)) {
					// BufferedReader in = new BufferedReader(new
					// InputStreamReader(zin));
					return zin;
				}
				zin.closeEntry();
			}
			zin.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String parseXml(InputStream is,String key) {
		try {
			AXmlResourceParser parser = new AXmlResourceParser();
			parser.open(is);
			while (true) {
				int type = parser.next();
				if (type == XmlPullParser.END_DOCUMENT) {
					break;
				}
				switch (type) {
				case XmlPullParser.START_DOCUMENT: {
					// log("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
					break;
				}
				case XmlPullParser.START_TAG: {
					if ("manifest".equals(parser.getName())) {

						int namespaceCountBefore = parser.getNamespaceCount(parser.getDepth() - 1);
						int namespaceCount = parser.getNamespaceCount(parser.getDepth());
						for (int i = namespaceCountBefore; i != namespaceCount; ++i) {
							// log("%sxmlns:%s=\"%s\"", indent,
							// parser.getNamespacePrefix(i),
							// parser.getNamespaceUri(i));
						}
						for (int i = 0; i != parser.getAttributeCount(); ++i) {
							if(key.equalsIgnoreCase( parser.getAttributeName(i))){
								return getAttributeValue(parser, i);
							}
//							System.out.println( parser.getAttributeName(i));
//							log("%s%s=\"%s\"", getNamespacePrefix(parser.getAttributePrefix(i)), parser.getAttributeName(i), getAttributeValue(parser, i));
						}
						// log("%s>", indent);
						break;
					}
					// log("%s<%s%s", indent,
					// getNamespacePrefix(parser.getPrefix()),
					// parser.getName());

				}
				case XmlPullParser.END_TAG: {
					// log("%s</%s%s>", indent,
					// getNamespacePrefix(parser.getPrefix()),
					// parser.getName());
					break;
				}
				case XmlPullParser.TEXT: {
					// log("%s%s", indent, parser.getText());
					break;
				}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	private static String getNamespacePrefix(String prefix) {
		if (prefix == null || prefix.length() == 0) {
			return "";
		}
		return prefix + ":";
	}

	private static String getAttributeValue(AXmlResourceParser parser, int index) {
		int type = parser.getAttributeValueType(index);
		int data = parser.getAttributeValueData(index);
		if (type == TypedValue.TYPE_STRING) {
			return parser.getAttributeValue(index);
		}
		if (type == TypedValue.TYPE_ATTRIBUTE) {
			return String.format("?%s%08X", getPackage(data), data);
		}
		if (type == TypedValue.TYPE_REFERENCE) {
			return String.format("@%s%08X", getPackage(data), data);
		}
		if (type == TypedValue.TYPE_FLOAT) {
			return String.valueOf(Float.intBitsToFloat(data));
		}
		if (type == TypedValue.TYPE_INT_HEX) {
			return String.format("0x%08X", data);
		}
		if (type == TypedValue.TYPE_INT_BOOLEAN) {
			return data != 0 ? "true" : "false";
		}
		if (type == TypedValue.TYPE_DIMENSION) {
			return Float.toString(complexToFloat(data)) + DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
		}
		if (type == TypedValue.TYPE_FRACTION) {
			return Float.toString(complexToFloat(data)) + FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
		}
		if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
			return String.format("#%08X", data);
		}
		if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) {
			return String.valueOf(data);
		}
		return String.format("<0x%X, type 0x%02X>", data, type);
	}

	private static String getPackage(int id) {
		if (id >>> 24 == 1) {
			return "android:";
		}
		return "";
	}

	private static void log(String format, Object... arguments) {
		System.out.printf(format, arguments);
		System.out.println();
	}

	// ///////////////////////////////// ILLEGAL STUFF, DONT LOOK :)

	public static float complexToFloat(int complex) {
		return (float) (complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4) & 3];
	}

	private static final float RADIX_MULTS[] = { 0.00390625F, 3.051758E-005F, 1.192093E-007F, 4.656613E-010F };
	private static final String DIMENSION_UNITS[] = { "px", "dip", "sp", "pt", "in", "mm", "", "" };
	private static final String FRACTION_UNITS[] = { "%", "%p", "", "", "", "", "", "" };


	public static String getVersionCode(String filePath){
		InputStream is = loadZipFile(filePath, "AndroidManifest.xml");
		return parseXml(is,"versionCode");
	}
	public static String getVersionName(String filePath){
		InputStream is = loadZipFile(filePath, "AndroidManifest.xml");
		return parseXml(is,"versionName");
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println(getVersionCode("c:\\רҵ��ѹ����.apk"));
		System.out.println(getVersionName("c:\\רҵ��ѹ����.apk"));
	}
}
